I'm going through an Android app I've ported from iOS and trying to figure out the causes of any warnings I'm getting and get my code in line with Android Studio's lint.
So far, most of the "problems" have been pretty easy fixes, but I've got a warning with a particular Parse.com API function that has me stumped.
Here's the code:
private void loadData() {
ParseQuery query = ParseQuery.getQuery("someClass");
query.include("someProperty1");
query.include("someProperty2");
query.include("someProperty3");
query.orderByAscending("sequence");
query.whereEqualTo("owner", ParseUser.getCurrentUser());
// This next line causes the warning
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> items, ParseException e) {
if (e != null) {
// Error handling here
} else {
// Got query results here
}
}
});
}
The warning that is showing up is:
Unchecked call to 'findInBackground(FindCallback < T >)' as a member of raw type 'com.parse.ParseQuery'.
When you allow autocomplete to "fill out" a new FindCallback for you, you get this:
query.findInBackground(new FindCallback() {
#Override
public void done(List list, ParseException e) {
}
#Override
public void done(Object o, Throwable throwable) {
}
});
Well, that's annoying, because the actual results that are returned are a List of type ParseObject. So, I edited that code to my code above in order to streamline my code. The interesting thing is that even the autocomplete code has the same warning associated with it.
I think I understand to reason that this warning is generated, but I've attempted as best I can to specify my types. Is there something more I can do to make my code work? Or rather, given that I can't re-write Parse's code, how do I correctly fix this warning?
You just need to type your ParseQuery:
Replace ParseQuery query with ParseQuery<ParseObject> query
Related
I'm using Parse as my backend and I'm trying to "like" a post that another user posted on the app. I'm querying to get the post, then incrementing the number of likes by 1, then adding the current user's object ID to an array that holds all the ID's of users which liked the post.
carLikeQuery.getInBackground(carItem.getObjectId(), new GetCallback<ParseObject>() {
#Override
public void done(ParseObject object, ParseException e) {
object.increment("likes");
object.addUnique("usersWhoLike", ParseUser.getCurrentUser().getObjectId());
object.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if(e==null) {
Log.d("SAVE", "Like saved :)");
} else {
Log.e("SAVE", "Not saved :( :" + e.getLocalizedMessage());
}
}
});
}
});
The error I'm getting:
E/SAVE: Not saved :( :java.lang.IllegalArgumentException: Cannot save a ParseUser that is not authenticated.
I saw the source code for the ParseUser from somewhere:
void validateSave() {
if (getObjectId() == null) {
throw new IllegalArgumentException("Cannot save a ParseUser until it has been signed up. Call signUp first.");
}
if (!isAuthenticated() && isDirty()) {
throw new IllegalArgumentException("Cannot save a ParseUser that is not authenticated.");
}
}
Doing the same kind of checking in my code reveals that the the currentUser is AUTHENTICATED and NOT DIRTY.
What could the issue be? To be honest, I want to say that it was working just fine before today, but obviously I was changing something and made a mistake down the line and I can't find it! Any help would be greatly appreciated.
I resolved the issue by creating an entirely new Parse application with the same data structure/layout. It just plain worked without any code changes.
You can follow the issue on GitHub here
On every launch my app loads fresh data from parse.com and pins all objects to use app without network requests like this^
public void pinKids() {
ParseQuery<ParseObject> query = ParseQuery.getQuery(ParseConstants.CLASS_KIDS);
query.whereEqualTo(ParseConstants.KEY_PARENT, currentUser);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(final List<ParseObject> kidsList, ParseException e) {
if (e == null) {
ParseObject.unpinAllInBackground(ParseConstants.LABEL_KIDS, new DeleteCallback() {
#Override
public void done(ParseException e) {
ParseObject.pinAllInBackground(ParseConstants.LABEL_KIDS, kidsList, new SaveCallback() {
#Override
public void done(ParseException e) {
Log.d("Hello", "pinKids");
}
});
}
});
}
}
});
}
One of the columns in my class is an array of strings (it stores history messages). I found that my code doesn't refresh this array if that array was updated from the other device (the same user did something on the other device). The rest of the data (other columns) refresh without problems. But the array of strings stays as it was downloaded at first launch.
In parse.com dashboard I see that array is updated. But code doesn't download this array while all the other columns are downloaded correctly.
Let me say that when I update this array on device-1 the new data is stored on device-1 and on "parse.com" too. But it doesn't update on device-2.
Please help!
OK! I've solved it.
This problem is a bug of parse.com.
I've created an issue on parse's github.
So I found that my problem is a part of parse's bug.
So the answer is: replace all calls to getJSONArray(key) with getList(key). You might also need revert()/revert(key)
Hello I am working on android app in which I am using parse cloud. I have signUp into the system then after I am trying to fetch data from parse.
But I am getting an exception everytime
com.parse.ParseRequest$ParseRequestException: invalid session token
String userName = ParseUser.getCurrentUser().getUsername();
ParseQuery<ParseObject> parseQuery = ParseQuery.getQuery("users");
parseQuery.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> list, ParseException parseException) {
}
});
How we can resolve this problem.
Googling and Parse docs didn't give too much info about this exception, but There are few common mistakes I found. You should treat users as ParseUser, not ParseObject.
ParseQuery<ParseUser> query = ParseUser.getQuery();
One more case: need to specify what to find in background. If it is username, so write:
parseQuery.whereEqualTo("username", userName);
And finally callback will contain List with ParseUsers, not ParseObjects
query.findInBackground(new FindCallback<ParseUser>() {
public void done(List<ParseUser> objects, ParseException e) {
}
});
I'm not sure exception will be gone, but I hope this answer will be useful anyways.
Some useful links: doc with example, answer, Doc for class ParseQuery with examples
UPDATE
This is the official doc how to handle this error, also as I commented try to use ParseUser.enableRevocableSessionInBackground() after Parse.initialize(); According to the SDK Documentation it is gonna update session token and only one case it could be invalid - ParseObject was removed.
Hope that helps.
I got this error when I was trying to login while I already logged in.
Try to call ParseUser.logout()
As Yurets said, you probably removed the session object. This can be solved quickly by uninstalling the app and then re-installing it.
I have an app which works with users, and offers the possibility to follow certain users, at the current user choice.
Unfortunately, I don't know how to modify data of a user which is not the current user. I have not seen anything like that stated in the Parse.com docs(or i missed).
I have a column in my database in "Users" class called "usersFollowed" and when the current user clicks "Follow" i want to add the current user to the "usersFollowed" list, but adding them like you will see in the following code does not work.
Follow user code:
dialog = ProgressDialog.show(context, "",
"Following...", true);
viewHolder.userFollow.setSelected(true);
viewHolder.userFollow.setText("FOLLOWING");
ParseQuery<ParseUser> userListQuery = ParseUser.getQuery();
userListQuery.whereEqualTo("screenName", parseUserList.get(position).get("screenName").toString());
userListQuery.findInBackground(new FindCallback<ParseUser>() {
#Override
public void done(List<ParseUser> parseObjects, ParseException e) {
parseUserFollowedList = new ArrayList<>();
if (parseObjects.get(0).getList("usersFollowed") == null) {
parseUserFollowedList.add(ParseUser.getCurrentUser());
parseObjects.get(0).addAll("usersFollowed", parseUserFollowedList);
} else {
parseUserFollowedList = parseObjects.get(0).getList("usersFollowed");
parseUserFollowedList.add(ParseUser.getCurrentUser());
parseObjects.get(0).addAll("usersFollowed", parseUserFollowedList);
}
parseObjects.get(0).saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
dialog.dismiss();
}
});
}
});
.saveInBackground does not work because it throws exception: Cannot save info for user that is not logged in".
Can anyone help me in how to do this?
Cheers!
Users may modify only their own data. But the idea of following can be implemented such that only the currentUser's record requires write access: If Jack chooses to follow Jill, then Jack writes to his "following" relation. This works as long as we don't try to represent "followedBy" in Jill's data (which can be achieved instead with a query).
Or consider that the User table represents the private relationship between a real person and your app. It might make better sense to model the idea of a user's public face with your own custom object, and model following relationships between those. I mention this idea elsewhere here and here.
I have a registered app on Parse with a signup/login system. Now I want to create an activity which grabs all the available users in the app and to display them one-by-one as a listview. Can someone tell me how can I do that?
Once you've setup your ListView's adapter you can call this whenever you need to update it's contents:
public void updateUsers() {
ParseQuery<ParseUser> query = ParseUser.getQuery();
query.findInBackground(new FindCallback<ParseUser>() {
#Override
public void done(List<ParseUser> userObjects, ParseException error) {
if (userObjects != null) {
mUserAdapter.clear();
for (int i = 0; i < userObjects.size(); i++) {
mUserAdapter.add(userObjects.get(i));
}
}
}
});
}
That updates my adapter which is plugged into my ListView. If you have more than 100 users you want to return you'll need to up the limit as I hear that's the default (then you have to page the results, not sure how yet)
Side note: As far as I know you can't Subclass the ParseUser at the moment (you can, but you then can't use that as the object you're querying with using ParseUser.getQuery() (Which would normally be done by ParseUser.getQuery(MyCustomUserClass.class) if you were to query a customised object.