ParseObject pinInBackground returning null objectId - android

I have a block of code in an Android project that creates a ParseObject and stores it in the local datastore. However, when I go to check the objectId in the done() callback method of pinInBackground() it returns null. If I switch from pinInBackground() to saveInBackground() then it works fine and a valid objectId is given. Here is the code:
final ParseObject testObject = new ParseObject("TestObject");
testObject.put("foo", "bar2");
testObject.pinInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e != null) {
Log.e(TAG, "Failed to pin TestObject: " + e.getMessage());
return;
}
Log.d(TAG, "Added key-value pair to TestObject '" + testObject.getObjectId() + "': 'foo' => 'bar2'");
}
});
The log shows:
Added key-value pair to TestObject 'null': 'foo' => 'bar2'
Why is the objectId null? Do I need to set it since it's not saving to the cloud?

The problem is that you are not saving object to the Parse database, only to the device, so the object has not actually been created yet. pinInBackground() is only saving to the device, while saveInBackground() is saving to the Parse database, thereby, actually creating the object. If you use .saveEventually(), that will pin until the network can be reached to save to the Parse database. But in general - you will not actually create an object by only saving to your device, it must be saved to the Parse database to create.

Related

Implement recursive function for SQLITE database

I am syncing lat-longs from local database to the server and change the status of rows in local database table if the lat-longs are successfully synced with the server, when user presses the button.
Problem
When button is pressed I hit the API for syncing lat-long to the server.
Some long-long is missing if the internet is slow (I want to send all lat-longs in exact sequence. If miss any lat-long, I try again to send the missing).
If all lat-longs are successfully synced only then EndRide Api is called.
This is the code when the button is pressed.
try {
cursor = db.getUnsyncedLatLngs(engIdForDB);
if (cursor.moveToFirst()) {
do {
//calling the method to save the unsynced name to MySQL
saveLatLngs(cursor.getInt(cursor.getColumnIndex(NewDatabaseForInRideData.COLUMN_ID)), cursor.getDouble(cursor.getColumnIndex(NewDatabaseForInRideData.Latitude)), cursor.getDouble(cursor.getColumnIndex(NewDatabaseForInRideData.Longitude)), engIdForDB);
} while (cursor.moveToNext());
}
} catch (Exception e) {
e.printStackTrace();
}
//Problem driverEndRideAsync is called even if some LatLng skiped to upload.
driverEndRideAsync(activity, abc, abc, 0, abc);
And for uploading lat-long to the server
private void saveLatLngs(final int id, final double lati, final double longi, String engId) {
RestClient.getApiService().update_data(abc, abc, lati, longi, String.valueOf(123), String.valueOf(123), String.valueOf(123), new Callback<String>() {
#Override
public void success(String s, Response response) {
try {
JSONObject jObj;
jObj = new JSONObject(s);
int flag = jObj.getInt("flag");
if (ApiResponseFlags.SOMETHING_WENT_WRONG.getOrdinal() == flag) {
db.updateNameStatus(id, NAME_NOT_SYNCED_WITH_SERVER, engId);
} else {
db.updateNameStatus(id, NAME_SYNCED_WITH_SERVER, engId);
}
} catch (JSONException e) {
e.printStackTrace();
}
android.util.Log.i("update_in_ride_data", " Success =" + response);
}
#Override
public void failure(RetrofitError error) {
android.util.Log.i("update_in_ride_data", " Error =" + error);
}
});
}
You have several problems in your implementation.
You are saving your lat-long fetched from your database table by calling an external API to your server inside a while loop. This is quite a bad implementation as this is creating a lot of AsyncTask in the background when you are trying to save each lat-long with an API service call.
The cleaner implementation requires development in your backend server which should take the lat-long as a batch (i.e. a bunch of lat-long will be saved at a time). In this implementation you will be able to save your lat-long by calling the API service once, instead of having it called multiple times for each of your entries.
Move the driverEndRideAsync(activity, abc, abc, 0, abc); function call inside your try block, so that it will not execute if you get an exception from that block while you are sending the lat-long data to your server using the API service.
If you are keeping this exact implementation in your server side, then I would suggest you to have a background service which will check if there is any data available to be synced with server in your database table after a certain time. In that case, you will have your data synced even if you get an exception while you are syncing your data with your server, because eventually the background service will detect un-synced data and will sync them with the server application.
Hope that helps.

Android - Parse - deleteInBackground, record not being deleted

I'm using Parse with Android in order to sync my data.
I'm trying to delete an object which is stored in the Parse cloud via
The callback returns and there's no exception, the Logcat message is "deleted".
But the object still exists in table when I check the Parse Data.
tastToEdit is an object from Task class (configured locally in my app).
ParseObject parse_task = new ParseObject("Task");
parse_task.put("Description",tastToEdit.getDescription());
parse_task.put("DueDate",tastToEdit.getDueDate());
parse_task.put("Priority",tastToEdit.getPriority().ordinal());
int com_state = (tastToEdit.getCompleted()) ? 1 : 0;
parse_task.put("IsCompleted",com_state);
parse_task.put("Location",0);
parse_task.put("Category",tastToEdit.getTask_catg().ordinal());
parse_task.put("Status", tastToEdit.getTask_sts().ordinal());
//parse_task.deleteInBackground();
parse_task.deleteInBackground(new DeleteCallback() {
public void done(ParseException e) {
if (e == null) {
Log.d("msg","deleted");
} else {
Log.d("msg", "not deleted");
e.printStackTrace();
}
}
});
What might be causing the callback to return as "deleted" but the object still remains?
Thanks in advance.
You are creating a new ParseObject and you try to delete it after but you don't provide an ObjectID.
A better way to do this will be to first do a ParseQuery for that task you are looking and the in the completion delete it.

Waiting for device token with parse Android

I am currently developing on Android and using Parse. My goal is to get the device Token and send it to a web service in order to register an install.
I have this code :
installation.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
// Saved!
if(e==null){
String deviceToken = (String)installation.get("deviceToken");
String objectId = installation.getObjectId();
Log.d("test","device token : "+deviceToken);
Log.d("test","object id : "+objectId);
}else{
Log.d("test","error : "+e.getMessage());
}
}
});
ObjectId is fine but I am always getting null for the deviceToken. But on my Parse.com back-end the DeviceToken is here and well defined...
So, what is the solution to avoid getting null and to send the right data ?
I found nothing about my problem in the parse documentation or Parse Android community.
Thank you very much for your answers.
I think you should use following method to get current installation. and then device Id - In above code, the save call back is not returning you the saved object
String deviceToken = ParseInstallation.getCurrentInstallation().get("deviceToken");
String objectID = ParseInstallation.getCurrentInstallation().getObjectId();
Hope it helps!
You can get installationID and work with it:
ParseInstallation installation = ParseInstallation.getCurrentInstallation();
String installationID = installation.getInstallationId();
because sometimes deviceToken is null

Accessing a custom column in Parse.com user table returning me null

I am trying to retrieve a new column called "address" I created in Parse User in my android app. But it returns me nullPointerException error and returns me nothing although I filled the address in the table.
This link only shows the way to store your custom field in the user table but I need to retrieve what I stored there.
This is my code:
ParseUser pUser = ParseUser.getCurrentUser();
userAddress.setText(pUser.getString("address").toString());
I tried get("address") as well but still it returns me nothing. Is there something I'm missing here?
Alright, I found the answer on my own. It turns out that Parse caches the ParseUser.getCurrentUser() object locally and the reason I wasn't able to get the data from server was because I changed the data on server and the client cache wasn't updated.
I was able to fix this by fetching the ParseUser object from the server:
ParseUser.getCurrentUser().fetchInBackground();
and then after the object is retrieved from the server I was able to get the address field on my client.
You need to call it using a Query, then display it in a textView/editText. Try the following:
final ParseQuery<ParseObject> address = ParseQuery.getQuery("//Class Name");
address.getFirstInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject reqAdd, ParseException e) {
if (address != null) {
Log.d("quizOne", "Got it");
//Retrieve Age
String //CreateNewString = reqAdd.getString("//Column name");
TextView //textView Name = (TextView) findViewById(R.id.//textView ID);
//textViewName.setText(//StringName);
Toast.makeText(getApplicationContext(),
"Successfully Recieved Address",
Toast.LENGTH_LONG).show();
} else {
Log.d("//EnterName", "//Enter Error Message");
Toast.makeText(getApplicationContext(),
"Can't receive address", Toast.LENGTH_LONG)
.show();
}
}
});
Short answer: that user probably just doesn't have an address set.
Long answer: your code snippet will throw exceptions often, and you should expect and handle those, or use tests to avoid throwing them.
Read this page: http://en.wikibooks.org/wiki/Java_Programming/Preventing_NullPointerException
Key example/excerpt:
Object obj = null;
obj.toString(); // This statement will throw a NullPointerExcept
So pUser.getString("address") appears correct. But calling .toString() on the result requires you to be try/catching the exception. Maybe do
ParseUser pUser = ParseUser.getCurrentUser();
if (pUser.getString("address") != null) {
userAddress.setText(pUser.getString("address"));
}
BTW, I believe the error is "nullPointerException" fyi! :)

com.parse.ParseException: Clients aren't allowed to perform the find operation on the installation collection

I am new to parse ,i am able to store data to its database but whenever i try to retrieve some information like object-id from database i usually get the above mentioned error.Query which i am using to retrieve the object-id corresponding to the given Friend-id.
ParseQuery<ParseObject> query = ParseQuery.getQuery("_Installation");
query.whereEqualTo("FriendId", FrndTextString);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> results, ParseException e) {
if (e == null) {
for (ParseObject x : results) {
String Objectid = x.getString("objectId");
objectidEditText.setText(Objectid);
}
} else {
Toast.makeText(getApplicationContext(),
"Error in retreving Data", Toast.LENGTH_LONG)
.show();
}
}
});
Please help me in solving this issue as I googled a lot but haven’t found anything good solution.Any help will be appreciated.
Thanks.
The _Installation class is an internal class from Parse. The exception occurs because you are trying to access data that is protected by a specific user with specifc ParseACL .
Documentation from Parse:
Every Parse application installed on a device registered for push notifications has an associated Installation object. The Installation object is where you store all the data needed to target push notifications. For example, in a baseball app, you could store the teams a user is interested in to send updates about their performance. Saving the Installation object is also required for tracking push-related app open events.
In Android, Installation objects are available through the ParseInstallation class, a subclass of ParseObject. It uses the same API for storing and retrieving data. To access the current Installation object from your Android app, use the ParseInstallation.getCurrentInstallation() method. The first time you save a ParseInstallation, Parse will add it to your Installation class and it will be available for targeting push notifications.
Try to use another Class, like "Ranking". Ex:
ParseQuery<ParseObject> query = ParseQuery.getQuery("Ranking");
query.whereEqualTo("FriendId", FrndTextString);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> results, ParseException e) {
if (e == null) {
for (ParseObject x : results) {
String Objectid = x.getString("objectId");
objectidEditText.setText(Objectid);
}
} else {
Toast.makeText(getApplicationContext(),
"Error in retreving Data", Toast.LENGTH_LONG)
.show();
}
}
});
You have to pay attention to setup ParseACL correctly for each user and Class, if you want to find public information of others users. At least, all user have to be "Public Read" for data that you want.
Before saving any data in Parse, you have to setup the environment with this tutorial. After, you have to Create the ParseUser and login with it. Parse has an automatic way to create an user, just calling:
ParseUser.enableAutomaticUser();
ParseUser.getCurrentUser().increment("RunCount");
ParseUser.getCurrentUser().saveInBackground();
To save any data in Parse, you can use:
ParseObject gameScore = new ParseObject("GameScore");
gameScore.put("score", 1337);
gameScore.put("playerName", "Sean Plott");
gameScore.put("cheatMode", false);
gameScore.saveInBackground();
Parse Server will automatically create the new class "GameScore", if is not exist. And will create all column, like "score", "playerNAme" and "cheatMode" if it not exist.
To go through with Parse, please read API Doc, it is so helpful.
The Installation class can't be queried like that. Use ParseInstallation.getCurrentInstallation(); instead.
for example,
ParseInstallation.getCurrentInstallation().getString("FriendId");

Categories

Resources