Saving locally stored parseobject to cloud - android

I am trying to save some data to parse cloud using this code:
ParseObject po=new ParseObject("Gamescore");
po.put("score",myscore);
po.saveInBackground();
I am successful in saving this object to parse cloud.But I need to store it locally first and then at sometime when user clicks a button, the parse object must update the table in the Parse Cloud and save it self in the cloud.Please don't consider the code as any game scenario,it is just an example,I am using.
I tried to understand parse.com documentation but it is not so much helpful.

Using local datastore https://parse.com/docs/android_guide#localdatastore
You can do something like:
ParseObject po=new ParseObject("Gamescore");
po.put("score",myscore);
po.pinInBackground(); // now it is saved locally
Then later when user press a button
ParseQuery<ParseObject> query = ParseQuery.get("Gamescore")
.fromLocalDatastore()
.findInBackground(new FindCallback() {
public void done(List<ParseObject> objects, ParseException e) {
// all Gamescores pinned locally
for (ParseObject score: objects) {
// keep in local database till successfully saved online
score.saveEventually();
}
}
});
Instead of saveEventually() you could of course also simply do saveAllInBackground() which is more efficient if you have many objects, but then it will timeout at some point if there is no internet connection.

Related

How to pause a ListIterator

Im using Firebase database to store my users scores games , at the end of the game users can see the final results of every members of the party
My users data and their scores are stored at 2 different places
here how looks my structure in Firebase.
Posts
-KLpcURDV68BcbAvlPFy
user_id: "KLpcURDV68BcbAvlPFy"
score: "A"
-asdasdasddsad
user_id: "asdasdasddsad"
score: "B"
Users
-KLpcURDV68BcbAvlPFy
id: "KLpcURDV68BcbAvlPFy"
name: "Jordan"
-asdasdasddsad
id: "asdasdasddsad"
name: "Tyler"
So I load first Id from Child (Posts ) inside an Arraylist and after I user the ListIterator to load data for every id in the Child(Users ) .
My question is simple . How can I pause a ListIterator
I have an Firebase onDataChanged Load inside a My ListIterator , it return null because my list finish faster than my Firebase load , How can I make my List wait for my Firebase database to load necessary data and then resume itself ?
My code
for (ListIterator<String> it = list.listIterator(); it.hasNext(); i++) {
String UserUid= it.next();
LoadataValue(UserUid, new OnObjectExistListener<String>() {
#Override
public void onDataChanged(Data userData) {
ListIterator must resume here
}
});
ListIterator must pause Here
}
You cannot pause a list iterator they way you want it to. Let me explain a little bit.
Firebase gets the data over the internet in a separate background thread and it should take some time to trigger that onDataChanged method whereas your list iterator might be running in the main thread. Hence, you will always have to wait for the background thread to be completed and return some data to your main thread to be able to show them. You can achieve the behavior in many different ways.
It looks like you are trying to get all the user details from the firebase. I assume, the simplified structure of your firebase database looks like the following.
users:
user1:
userDetails:
name: Everyone
user2:
userDetails:
name: Needs
user3:
userDetails:
name: some
user4:
userDetails:
name: help
You can try getting all the values at once from the users node, and store them locally (maybe inside a List<User>). Then once the list of users are downloaded correctly in your onDataChange function, trigger your list iterator in a separate method so that it can go over that locally stored list and provide you the results that you want.
Here's a pseudo implementation.
// Get a reference to your users
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("your-firebase-url/users");
// Attach a listener to read the data from your firebase database
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<User> users = dataSnapshot.getValue(User[].class);
callAFunctionThatRunsThroughThisListOfUsers(users);
}
});

How structure a SQLite database for offline support?

I'm trying to give the offline support in my app, so user can read the information without the internet also. I'm creating an app to show some packages from different companies. I have created my API and following database in the remote server.
companies -- id, name
duration-- id, type (type could be, monthly, weekly, yearly)
packages -- id, name, company_id, duration_id
My API is returning result as
{
"id":3,
"package":"premimum",
"company_id":6,
"duration_id": 5,
}
Now I want to store all information fetched from the API to the local database SQLite. Now I want to know how I should structure my local database? should I structure same as the remote database? should I create the three tables in the local database SQLite same as?
companies -- id, name
duration-- id, type (type mean package duration, monthly, yearly, daily)
packages -- id, name, company_id, duration_id
If yes then id will be different in local database and in the remote database, because both databases will generate own primary key how I can handle this? or something you can suggest me to keep the same ID? or should I keep the id different?
You don't necessarly need the internal Ids on your local database to match those of your cloud server database. For instance, if you use Parse as cloud server, Parse will generate its own internal object ID. Your app does not need to know them.
Having said that, I strongly suggest you have a common key attribute between your local object and cloud object, so that you can keep them synced.
For example you could add a package_id attribute on both your local and cloud object. This package_id will be the same on both side, so that you can update your local object when the remote object is updated and vice-versa.
For example, here is the code to create an object on the Parse server:
ParseObject gameScore = new ParseObject("GameScore");
gameScore.put("score", 1337);
gameScore.put("playerName", "Sean Plott");
gameScore.put("cheatMode", false);
gameScore.saveInBackground();
You can them retrieve this object from the app as follows:
ParseQuery<ParseObject> query = ParseQuery.getQuery("GameScore");
query.getInBackground("xWMyZ4YEGZ", new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
// object will be your game score
int score = object.getInt("score");
String playerName = object.getString("playerName");
boolean cheatMode = object.getBoolean("cheatMode");
} else {
// something went wrong
}
}
});
I suggest you read the documentation for more infos on storing object on a Parse server:
https://docs.parseplatform.org/android/guide/
Also, this lib could help you to sync data between local database and a Parse server:
https://github.com/ntoskrnl/DataSync

Connect users and Firebase Database

So I am keeping track of a users taps on the screen and I have the user sign up with their email. However, when it comes to using the Firebase Database I am lost. I am not sure, how to save integers and then it load up when the user logs in. Can someone point me in the right direction?
I have watched a ton of videos and none show how to store information with an integer.
You don't need to do anything special for storing a integer or any other value in the Firebase DB.
You can use the uid of the current user and store the pojo/model directly into the the firebase DB.
For example, this can be your java model class:
public class Model {
private int tapCount=0;
public int getTapCount() {
return tapCount;
}
public void setTapCount(int tapCount) {
this.tapCount = tapCount;
}
}
When you want to insert the tap count into the Firebase db. You need to take the previous tap counts and add it with the current count update/create the Model object and set it into the Firebase db in the uid.
FirebaseDatabase.getInstance().getReference()
.child("user")
.child(FirebaseAuth.getInstance()
.getCurrentUser()
.getUid())
.setValue(model);
This code will insert the model under the user key and under user unique id.
Thanks,
Hope it helps.

Parse query not returning new data on onResume

I'm developing a feature where users can join a room and I'm using Parse to hold the room's data. My problem is that when a new user joins a room and an existing user of that room resumes the room's activity, the existing user doesn't see the new user.
So here's an entry for my table where a user created a room but no one's joined yet.
Here's my GameOnSession class which is an extension of the ParseObject class.
#ParseClassName("GameOnSession")
public class GameOnSession extends ParseObject {
public JSONArray getParticipants() { return getJSONArray("participants"); }
public String getNumberOfParticipants() {
int getParticipantsNumber = getParticipants().length();
return String.valueOf(getParticipantsNumber);
}
public static ParseQuery<GameOnSession> getQuery() {
return ParseQuery.getQuery(GameOnSession.class);
}
}
This is my query that I run to check the number of people in the room.
ParseQuery<GameOnSession> query = ParseQuery.getQuery(GameOnSession.class);
query.whereEqualTo("objectId", QueryPreferences.getStoredSessionId(getActivity()));
query.findInBackground(new FindCallback<GameOnSession>() {
#Override
public void done(List<GameOnSession> objects, ParseException e) {
GameOnSession sess = objects.get(0);
Log.d("GAMEONSESSION", "Current # " + sess.getNumberOfParticipants());
}
});
So it returns what I expect: 0.
Now when a new user joins the room, the entry looks like this.
Then I press a button that runs the query above. And it still returns 0, when I expect 1.
I'm not sure what's the problem here, did I set up my query wrong?
In short, when User A creates a room, the Parse query returns number of users as 0 which is expected. When User B joins User A's room, Parse query STILL returns the numbers of users as 0 and NOT 1. This is unexpected and I'm not sure how to proceed.
So I found out the cause of why my application wouldn't correctly query the database. The reason was that I called Parse to "enableLocalDatastore" so whenever I tried a new query, the application would query from the cached result.
So what I did was disable local datastore and everything's working as expected.
Funny thing was, my team and I that's building this application enable local datastore in the beginning of the development cycle (6 months ago) to test a small feature and forgot to disable it. Technical debt is a PITA.
So if your Parse query is not returning what you expect even though the database clearly shows what you've done, check that you haven't enabled your local datastore!

One to many relation on Parse.com

I have two classes on Parse.com : Image & User. In User class, I am saving 3 fields Name,Mobile-number & Occupation. In Image class I'm saving images.
I have to create one-to-many relation between these two classes so that I can fetch images with the corresponding mobile-number.
I have created a relation between User class and Image class on parse.com with a column named Mobile in User class. Not able to find how can I fetch the images with that particular mobile number with one-to-many relation. Please help as I have gone thru the documentation. Thanks in advance.
This is just the code to go about. You will have to think about organizing your classes thoughtfully. I am not sure how you intend to go but as far as coding is involved, the following should help.
First get the current user.
ParseUser currentUser = ParseUser.getCurrentUser();
Since, you have "mobile" column as the relation in the User table, get the relation first.
Like this.
ParseRelation<ParseObject> relation = currentUser
.getRelation("mobile");
Once you get the relation, get the query on the object who require. In your case, it is the Image Object.
ParseQuery<ParseObject> query = relation.getQuery("Image");
From here, you can customize your query. Eg:
query.getFirstInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject, ParseException e) {
if(e == null)
//your code
//List<ParseFile> pFileList = (ArrayList<ParseFile>) object.get("images"); //something like this just to give an idea
}
});
Or if you have multiple objects, use
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> list, ParseException e) {
if (e == null) {
for (ParseObject object : list) {
ParseFile image = (ParseFile) object.get("images_column_name");
}
}
}
});
If an Image class only has one User it is related to, simply use a reference property. You could call it owner or user or whatever. You then just set this to the current user (or any other user).
Internally Parse will store just the ID of this object with some extra information to make this as a link to another class.
When you query you can simply use the current user (or any other user) to compare against that property. Again, Parse will internally just compare ID's, you don't have to think about it.
Look at the documentation here. See where it sets the parent property of the Comment to an instance of the Post? That's the sort of thing you want to do.
Using the mobile number to link is a bad idea, as if you change the number on a User then all the Image classes using that number are now orphaned, unless you write extra code to handle this.

Categories

Resources