I am creating an android application for school which let people sign in, for this i used Parse.
My activities for signing in are in this way:
- the first activity, the student enter the email address and passeword and retape passeword, when he push the button, parse verify the email if it doesn't exist if the signing in is secusseful the second activity start.
-The second activity containt text field to complete the profil (FirstName, LastName, Age....).
In Parse.com :
In the Users class I've add new columns (FirstName, LastName,Age...)
My problem is that when the user complete the profil and accept, the data of FirstName, LastName...etc will be add in the Users class of Parse.com to complete the row of the current user signing in.
I've used in the second activity SignInBackground but it bug caus it demand a username (wich is already entered in the first activity), I also used SaveInBackground and also ParseObject but it create a new class.
I'm assuming you're calling signUpInBackground(SignUpCallback callback) in your first Activity.
Here's the Parse documentation about that method:
public void signUpInBackground(SignUpCallback callback)
Signs up a new user. You should call this instead of ParseObject.save() for new ParseUsers. This will create a new ParseUser on the server, and also persist the session on disk so that you can access the user using ParseUser.getCurrentUser().
A username and password must be set before calling signUp.
This is preferable to using ParseUser.signUp(), unless your code is already running from a background thread.
Parameters:
callback - callback.done(user, e) is called when the signUp completes.
So, what you can see is that this method both registers the user with Parse and logs in the user, persisting that login session to disk.
Therefore, when you get to your next Activity, you have no need to sign up or log in. You can simply get the new values from the user and then access the current user (ParseUser.currentUser()), adding the values to that object in a manner like this:
ParseUser user = ParseUser.currentUser();
user.put("attribute1", "value1");
user.put("attribute2", "value2");
user.put("attribute3", "value3");
user.put("attribute4", "value4");
// And so on...
user.saveInBackground(); // You might want to implement a SaveCallback there
FYI: The saveInBackground() method is inherited from ParseObject.
If I am understanding your problem correctly it is that you don't have the data available for the username when you are calling saveInBackground in Activity 2. If this is the case I think the best option would be to pass the data you need (username etc) in the intent when you load the second activity.
To add the username to the intent you would do something like this.
String usernameText = "";
Intent ii=new Intent(Activity1.this, Activity2.class);
ii.putExtra("username", usernameText);
startActivity(ii);
Then to retreive the username in OnCreate method of Activity 2 you would do something like:
Intent iin= getIntent();
Bundle b = iin.getExtras();
if(b!=null)
{
String username =(String) b.get("username");
}
Obviously in my solution, I have assumed that you will retrieve the username from an EditText, but haven't put this into my code, as I have assumed you know how to do this already. Also in Activity 2 once you retrieve the username you will need to store it as a global variable, so that it can be used once the user finishes filling out the form on Activity 2.
Related
my Question is :
1 - If I send data to another activity where does it stored ?
2- what is the difference between put the parameter key of putExtra() method as builtin predefined string like EXTRA_TEXT and put a key with a random name
like "mymessage"
i.e
what is the difference between this code
public void go(View view)
{
String mytxt="hellow";
Intent i=new Intent(this , SecondActivity.class);
i.putExtra(Intent.EXTRA_TEXT , mytxt);
startActivity(i);
}
and this code
public void go(View view)
{
String mytxt="hellow";
Intent i=new Intent(this , SecondActivity);
i.putExtra("mydata" , mytxt);
startActivity(i);
}
3- how does android use the key part to of putExtra method to refer to my data
4- how does getExtra() method work from where it get the data
I think that 3 ans 4 are relevant by nature to the other above parts but I want to be clear about all my questions
thanks in advance
1 - If I send data to another activity where does it stored ?
I think there are a few different ways to answer this question, but the most straightforward is: it doesn't matter.
When you use an Intent to send data to another activity, what matters is that the other activity will receive an Intent object that is populated with the data you sent. The exact mechanism of how that happened is something you (as a developer) aren't supposed to care about.
The only exception to this that's worth mentioning is the fact that data in an Intent might (depending on exactly what you're doing) be subject to "Binder transaction size limits"; your data is serialized and transmitted at some point and, if the data is too large, this will fail.
2- what is the difference between put the parameter key of putExtra() method as builtin predefined string like EXTRA_TEXT and put a key with a random name like "mymessage"
There is no technical difference. In fact, Intent.EXTRA_TEXT is defined as a simple string itself ("android.intent.extra.TEXT").
The practical difference is that Intent.EXTRA_TEXT is a well-defined, known value that any developer can use. If I'm writing a chat program, and I want to let other apps open mine and hand off message text, I can tell users that I'll look for Intent.EXTRA_TEXT for this data, and it will be easy for everyone to use.
Within your own app, it really doesn't matter what strings you use for the key in a putExtra() call. As long as you use the same string later on to look it up, you can use anything you want. The only concern here is to make sure that you don't accidentally use the same key for two different values within the same Intent.
3- how does android use the key part to of putExtra method to refer to my data
It doesn't. All the android framework does is take a bunch of key-value pairs, serialize them (if necessary), and transmit them to another activity. That other activity, however, can then use the keys to look up the values. That's why e.g. Intent.EXTRA_TEXT is cool; it's a well-defined key that anyone can use to look data up, counting on callers on the other side to have put something in the map using that known key.
4- how does getExtra() method work from where it get the data
I guess you could say that the data comes from the app's memory.
You can think of the Intent object as being a really fancy Map<String, ?>. The same way you could write String s = (String) map.get("key"), you can write String s = intent.getStringExtra("key").
Your answers are as follow.
1. When we move from one Activity to another Activity, then data is passed using Intent and this data is sent to the system OS for safe keeping for restoration later, when we reach to another activity this data is restored from OS, There is a limit of 1 MB of this data, If It crosses then we get a crash
"TransactionTooLargeException" for nougat+ android devices.
2. Intent.EXTRA_TEXT is basically a predefined string in Intent class.
public static final String EXTRA_TEXT = "android.intent.extra.TEXT";
Google has coded internally for this key, suppose If we want to share a text with an application then we send this predefined key to send that "text" which need to be shared, thus It is a Standard Reserved key for which Google has coded internally to get and utilize that text
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_TEXT, "my sharign text here");
and on the other side, If we send any our key suppose "my_key" then we handle this on the other activity.
3/4.
When you pass on data from Activity 1 using putExtra() method, then all the data sent through putExtra() is packaged into a bundle, We can fetch this whole bundle in Activity2 using getExtras() method, or we can get our separate key value using getStringExtra(), getIntExtra(), getBooleanExtra() etc.
If you send extras to an activity, the extra data is not stored in a physical device like internal/external storage, but it is stored temporarily in RAM.
Intent.EXTRA_TEXT is a constant defined in the class Intent:
public static final String EXTRA_TEXT = "android.intent.extra.TEXT";
it is used with intents like sending emails and not passing data to activities, although it is not prohibited.
(and 4) The key part of the extra data is used to refer to the actual value of the data:
intent.putExtra("key1", "A");
intent.putExtra("key2", "B");
when the activity that opens wants to retrieve the extra values sent to it by the parent activity, it will check the keys:
if(getIntent().hasExtra("key1"))
String value1 = getIntent().getStringExtra("key1", "");
I'm working in an android app adding the following/follower system, I'm using the lines in the Parse.com, I have a user profile, and when I click on the follow button the app send the both users id (the current user and the other user) in a row. I'm using pointers targeting the _user class.
This is my current code :
Intent i = get intent();
String userId = i.getStringExtra("userid");
ParseObject follow = new ParseObject("Follow");
follow.put("from",ParseUser.getCurrentUser());
follow.put("to", userId);
follow.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
btn_follow.setImageDrawable(getResources().getDrawable(R.drawable.ic_following));
}
});
The btn_follow change the image. which means the following has been done. but my Follow class is empty.
I have changed my Follow table from :
...|from|to|
To :
...|from|to|
This worked well the both users id were saved, but I need pointers not string so I put from and to to pointers again and deleted the line
follow.put("to", userId);
This worked well also but it only saved the current user and not the user I'm trying to follow.
So my problem is with the ID of the user I want to follow.
In the guide they are saying
"ParseUser otheruser = ..."
(I don't no what to put in the 3 points to get the other user id)
You need to assign a ParseObject (or ParseUser) to create a pointer in database. For this you need to create ParseUser without data, just with id like this:
follow.put("to", ParseObject.createWithoutData("_User", userId));
Also, you should check the ParseException e in callback to see whats going on.
I am letting the user change his credentials.
He types new username, email and password and I go like:
ParseUser user = ParseUser.getCurrentUser();
user.setUsername("MY NEW NAME");
user.setEmail(email);
user.setPassword("MY NEW PW");
user.saveInBackground(...);
So what? So this save() call might fail, for a big number of reasons (example: username already taken by someone else). I can tell that in this case none of the above fields gets updated, which is fair: I show an error, user knows that all went wrong.
Things get complicated if you notice that, even after the ParseException, the user above keeps its dirty fields, which couldn't be saved to the server. I.e.
//saveInBackground fails
//...
user.getUsername().equals("MY NEW NAME") // true!
Issue
Now, I am able to get these fields back to the right values by calling user.fetch(), but this doesn't work with the password field.
This is particularly unwanted, because any future call to save() or such (which might not fail because maybe it's a completely different call) will update the password too! I.e.
//later
ParseUser user = ParseUser.getCurrentUser();
user.put("stuff");
user.save();
This won't only put "stuff", but also change the password to "MY NEW PW".. without the user ever knowing.
Is there any way to reset the local password field, other than fetch() which doesn't work? I know I could save username, email and password with three different queries but that is not a possible solution for my case.
A workaround could be to use
+ becomeInBackground:
on PFUser class (with PFUser.currentUser().sessionToken as token) when save fails, but that is still a risk for becomeInBackground to fail.
It could at least prevent some cases to happend if becomeInBackground effectively undoes setPassword, and accepts current sessionToken as parameter, I haven't tested that
Looking at the newest release I've read in the changelog:
V1.10.2 — SEPTEMBER 15, 2015
New: Added ParseObject.revert() and revert(key) to allow reverting
dirty changes
Looks like this could be it. It was definitely needed.
If it was my problem I would try to create an oldUser first and save all current data to it, then when failing, it would be time to change every thing back to normal value, or if success it is time to kill oldUser. Hope it may help.
The password plain text is not stored in Parse and as such it cannot be obtained by your app. Found it here https://www.parse.com/questions/get-current-users-password-to-compare-it-with-a-string
If you want to change password you can use ParseUser.requestPasswordResetInBackground() so you will change the password with the help of email.
But if you need to get password really hard, you can store it in the SharedPreferences after the login.
After some test and check, here are some conclusion.
In parse, "password" is a special field, you cannot access it by ParseUser, That is way ParseUser have setPassword() but haven't getPassword() method
Even in back-stage management [Core] - [Data] - [User], you can see "password" field is Hidden
That is why fetch() method cannot recover original "password" value
So, I think if want implements above you need, try this way
// First time register //
ParseUser user = ParseUser.getCurrentUser();
user.setUsername("MY NAME");
user.setEmail(email);
user.setPassword("MY PW");
user.put("_password", "MY PW");
// The key can't use "password", this's reserve key word in Parse //
user.saveInBackground(...);
// Next time update //
user.setUsername("MY NEW NAME");
user.setPassword("MY NEW PW");
user.saveInBackground(...);
// if have something exception //
user.fetch();
// user.setPassword(user.get("_password"));
user.save();
ParseUser.login("MY NAME", "MY PW"); // Error
ParseUser.login("MY NAME", "MY NEW PW"); // Ok
user.fetch();
user.setPassword(user.get("_password"));
user.save();
ParseUser.login("MY NAME", "MY PW"); // OK
i have created my app, in which I have created several users. The challenge is, I need to construct the app in a way that, while I am logged in as a user (say User A), I can add input an object into another user (say User B). So, while am logged in as user A, I can input the data that will be saved into one of the empty field, of User B. Can you assist which way, I can arrange this? In short, how can I create an object to associate with the User B.
Here is the thing, while I am logged in as User A, I want to add "Scores" for both user A and B. for instance, if the user A's score is 7, and B's score is 20, I could add the scores while logged in the activity A, and they will be added in the field "Scores" of the corresponding users.
you should go for parse cloud code which is written in java script
refer this link to know more
https://parse.com/docs/js/guide#cloud-code
then you just edit main.js
deploy and call that cloud code from your code
// Use Parse.Cloud.define to define as many cloud functions as you want.
// For example:
Parse.Cloud.define("updateTable", function(request, response) {
var currentUserId=request.params.currentLoggedinUser;
var userToBeUpdatedId=request.params.userToBeUpdated;
var User = Parse.Object.extend('_User'),
user = new User({ objectId: userToBeUpdatedId });
user.addUnique("followers",currentUserId);
Parse.Cloud.useMasterKey();
user.save().then(function(user) {
response.success(user);
}, function(error) {
response.error(error)
});
});
deploy this code using comand "parse deploy" from terminal.
call this code from your code like
ParseCloud.callFunction("updateTable", params);
i hope it will help.
The way that Parse is setup by default is so that only the current users data can be editted in the User table. You could probably change the settings for the table however, this could cause security issues.
What I would suggest would be to create a 'Scores' tables. There you could have a row for each user. with a 'userID' column which contained the objectId of the user to reference the user. You could then have a score column which you could update whenever you wanted.
Alternatively to storing the objectId of the user in the userID column you could make an association between the Scores row and the user. See the Parse documentation for how to create associations. https://parse.com/docs/android_guide#users-associations
I was wondering how the most used apps keeps the login?
When I open Facebook, Twitter, Instagram or 500px my apps are ready without no time of login and I need to know the how-to for my apps, who request 8-10 seconds to login and download the user list.
EDIT: I'm not talking about the "cookie" for credentials. If you try Facebook, for example, you can see that the first login took 30 seconds, and then it is always connected. The other time you open Facebook, it doesn't ask for credentials for Shared Preferences, but it doesn't take 30 seconds to login. Why?
I believe all the Above posts are accurate but i wanted to add my two cents. When your application launches you should make a call in your Launcher Activity (activity that launches when your app icon is clicked on home screen if its not already open) to
// This will get you an instance of your applications shared preferences.
SharedPreferences preferences = getBaseContext().getSharedPreferences("MyPrefs", SharedPreferences.MODE_PRIVATE);
// Values
String userName = preferences.getString("username",null);
String password = preferences.getString("password",null);
// Then you want to query preferences for values such as username and password like
if((userName != null) && (password != null))
{
// **** Log your user into your application auto**Magically** ********
// ------------------- Option 1 - web request -------------------
// First i Would make the initial Web Request before trying to send my User into
// a new Activity.
// Run an `AsynchTask` against your webservice on the server if this is something
// you need to do to see if the username and password, are correct and registered
//---------- Option 2 - Check the SQLite Database(if you are using one) ---------
// Otherwise you can use this info to read from an SQLiteDatabase on your device.
// To see if they are registered
// This is where you would create a new intent to start
// and Login your user, so that when your application is launched
// it will check if there are a username and password associated to the
// Application, if there is and these are not null do something like
// Create a new Intent
Intent automagicLoginIntent = new Intent(getBaseContext(),AutomagicLogin.class);
// Pass the Bundle to the New Activity, if you need to reuse them to make additional calls
Bundle args = new Bundle();
args.putString("username", userName);
args.putString("password", password);
automagicLoginIntent.putExtra("UserInfo", args);
// Launch the Activity
startActivity(automagicLoginIntent);
}else{
// Show the Layout for the current Activity
}
This should be done in your onCreate(Bundle savedInstanceState); method but that is the short of it. It should not be too tricky to implement but the implementation is dependent on how your logic works.
Do you read from SQLIte Database ?
Do you read from WebService ?
etc.
But this should be all you need, unless you need to store some other values in the prefs.
Side Note
All the code above will not work if you have no way of getting this information from the user in the first place, i.e. a registration form.
When thinking of registration, you can initially store these values with the following code:
// Inside an Listener , get a reference to your `TextView`s that were used to enter
// username and password
TextView usernameText = (TextView) findViewById(R.id.textViewUsername);
TextView passwordText = (TextView) findViewById(R.id.textViewPassword);
// Get a reference to the SharedPReferences, SO WE CAN BEGIN TO STORE THE VALUES ENTERED
SharedPreferences preferences = getBaseContext().getSharedPreferences("MyPrefs", SharedPreferences.MODE_PRIVATE);
// Need this to Edit Preferences
SharedPreferences.Editor editor = preferences.edit();
// Then you can add the values
editor.putString("username",usernameText.getText().toString().trim());
editor.putString("password",passwordText.getText().toString().trim());
// Must Call this to write values to the Preferences
editor.commit();
And that should be all you need, to initially store the values and read them back from preferences to automagically login your user each time ur application is launched if it has not been opened, if it has been opened android activity lifecycle should reload the current activity that was last paused.
Good Luck!
You should save an authentication token for each user, you don't need to explicitly reauthenticate every time the user opens the app. When the app makes subsequent API calls, use that authentication token and send it to your back-end. If the back-end tells you that your authentication is invalid, then you know you need to reauthenticate.
They store the token using sharedPreferences
http://developer.android.com/reference/android/content/SharedPreferences.html