How to call Parse Cloud Code functions from my Android application? - android

I have already uploaded the function on parse using parse deploy command and i have a data class named Review along with few entries which is displaying in my Parse Core Dashboard.Here is my cloud code function:
Parse.Cloud.define("averageStars", function(request, response) {
var query = new Parse.Query("Review");
query.equalTo("movie", request.params.movie);
query.find({
success: function(results) {
var sum = 0;
for (var i = 0; i < results.length; ++i) {
sum += results[i].get("stars");
}
response.success(sum / results.length);
},
error: function() {
response.error("movie lookup failed");
}
});
});
Here is my Android Function:
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("movie", "The Matrix");
ParseCloud.callFunctionInBackground("averageStars", params, new FunctionCallback<Float>() {
public void done(Float ratings, ParseException e) {
//done action
}
});
This is what i am getting in the log:
NO RESPONSE:ParseRequestException: invalid session token
Please help.

Try including Parse.Cloud.useMasterKey(); in your cloud code function. Also make sure that you have correctly implemented logging in the user from which the cloud function is called.

Related

Count Parse installation records

Is there a way to count the number of Parse installations records?
I could not query in my App so I did it using cloud code. But still I can't query.
I'd like to count the number of installations per versionNumber and show this in my Admin Activity in the App.
Any Suggestions?
Error when trying to do a count via cloudecode:
- Clients aren't allowed to perform the find operation on the installation collection.
- Error generating response. ParseError {
code: 141,
message: 'Clients aren\'t allowed to perform the find operation on the installation collection.' }
Key to the solutions was adding: useMasterKey: true
Parse.Cloud.define("countInstallations", function(request, response) {
var qInstallation = new Parse.Query(Parse.Installation);
var sVersion = request.params.version;
var sResult = "";
qInstallation.equalTo("versionNumber",parseInt(sVersion));
qInstallation.count({
useMasterKey: true,
success: function(number) {
sResult = number;
response.success(sResult);
},
error: function(error) {
response.error(0);
}
});
});
From my App I call this cloud function like this which will return the count for version 39.
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("version","39");
try {
Log.d("MyApp","result:" +ParseCloud.callFunction("countInstallations",parameters));
} catch (ParseException e) {
e.printStackTrace();
}

Parse cloud function send JSON to specific user

I create an App that a user can send messages(notifications) in other users. Fot these perpose i use parse SDK. So i send the message from device into the parse cloud with below code.
final ParseQuery<ParseUser> query = ParseUser.getQuery();
query.whereEqualTo("email", "user#email.com");
query.getFirstInBackground(new GetCallback<ParseUser>() {
public void done(ParseUser object, ParseException e) {
if (e == null) {
Toast.makeText(getActivity(), "User found", Toast.LENGTH_SHORT).show();
String search_username = object.getString("username");
String id = object.getObjectId();
Log.d("ObjectID:",id);
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("recipientId", id);
params.put("message", username);
ParseCloud.callFunctionInBackground("sendPushToUser", params, new FunctionCallback<String>() {
public void done(String success, ParseException e) {
if (e == null) {
// Push sent successfully
Toast.makeText(getActivity(), "Request send", Toast.LENGTH_SHORT).show();
}
}
});
Then i have the next cloud function for recieve and push the message to the specific user.
Parse.Cloud.define("sendPushToUser", function(request,response){
var senderUser = request.user;
var recipientUserId = request.params.recipientId;
var message = request.params.message;
var title ="Friend Request";
if(message.length > 140){
message = message.substring(0, 137) + "...";
}
var recipientUser = new Parse.User();
recipientUser.id = recipientUserId;
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.equalTo("user", recipientUser);
Parse.Push.send({
where: pushQuery,
data: {
"alert":{"data":{"message":"message",
"title":"title"}}
}
}).then(function(){
response.success("true")
}, function(error) {
response.error("Push failed to send with error: "+error.message);
});
});
But the message never been received. If i sent a push notification from parse dashboard everything works fine. Anyone knows how to solve it? The device expect a JSON to received so may my cloud function didnt send data in json format? Thanks in advance
I had problems while sending notifications because of 2 things
enabling client push "not in your case"
didn't save the user in the installation "try the following"
After the user logs into your app add his id to the installation by
ParseInstallation installation = ParseInstallation.getCurrentInstallation();
installation.addUnique("userId", currentUser.getObjectId());
installation.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
// check the returned exception
if (e == null) {
// everything worked fine
} else {
// error occurred
}
}
});
hope it helps :)
Update
In your code you're sending the recipient userId although you saved the username also in your cloud function you have the same problem, the username is saved but you query the installation based on the id. I've updated the installation above also change the "user" in your cloud function to the "userId"
pushQuery.equalTo("userId", recipientUser);

How to Store Multiple records in My Array List from Azure mobile service Using API Code?

I created completeall2 API in Azure Mobile service..
My API Coding
exports.post = function(request, response) {
var mssql = request.service.mssql;
var sql = "SELECT * from productmovement";
mssql.query(sql, {
success: function(results) {
response.send(200, results);
} }) };
What's Code for store this results into my ArrayList<ProductMovement> in my app..
Please see the Mobile Services reference for querying data from an Android client:
https://azure.microsoft.com/en-us/documentation/articles/mobile-services-android-how-to-use-client-library/#querying
What i did to overcome this problem, is to call a different overload of invokeApi that returns a JsonElement, and then deserialise it into my objects like so:
mClient.invokeApi("productmovement",new ApiJsonOperationCallback() {
#Override
public void onCompleted(JsonElement jsonElement, Exception e, ServiceFilterResponse serviceFilterResponse) {
GsonBuilder gsonb = new GsonBuilder();
Gson gson = gsonb.create();
JsonArray array = jsonElement.getAsJsonArray();
List<MyObject> myObjects = new ArrayList<MyObject>()>
for(int i = 0; i < array.size(); i++)
{
myObjects.add(gson.fromJson(array.get(i).getAsJsonObject().toString(), MyObject.class));
}
}
});

Android: How to input values to Parse cloud code, eg beforesave

Inside a app, users will upload slot results with period name to the Parse Database. However, before upload, it would be much preferred if beforesave, checked whether the period ref is already there, if the same period ref is existing in the DB, the slot result would not be uploaded.
Cloud.beforesave
Parse.Cloud.beforeSave("check_duplicate", function(request, response)
{
var DB = Parse.Object.extend("Record_db");
var query = new Parse.Query(DB);
query.equalTo("period_ref", request.object.get("period_ref"));
query.first
({
success: function(object)
{
if (object)
{
response.error("A Period with this ref already exists.");
}
else
{
response.success();
}
},
error: function(error)
{
response.error("Could not validate uniqueness for this period ref object.");
}
});
});
Android code:
ParseCloud.callFunctionInBackground("check_duplicate", new HashMap<String, Object>(), new FunctionCallback<String>() {
public void done(String result, ParseException e)
{
if (e == null)
{
Utilities.custom_toast(CurrentResult.this, "cloud success" + result, "gone!", "short");
}
else
{
Utilities.custom_toast(CurrentResult.this, "cloud error" + e, "gone!", "short");
}
}
});
Question:
There is no clear example for such common situation. I would like to ask
for example, now the user would like to upload slot ref 001/2015 results. All info are already available at device, how could I pass this period reference 001/2015 to the cloud code for checking whether it is already existing in the Cloud DB uploading and saving to the Cloud DB?
Thanks a lot!
your first line of Android...
ParseCloud.callFunctionInBackground("check_duplicate", new HashMap(), new FunctionCallback() {
becomes
ParseCloud.callFunctionInBackground("check_duplicate",
new HashMap<String, String>{"period_ref":"001/2015"};,
new FunctionCallback<String>() {

Parse.com ParseQuery inconstancy

I have a very weird situation. I have an application where I am implementing a "Notification History".
I have a separate application that sends push notifications to targeted channels and then creates an entry into a table called Notifications, saving the channel that was targeted and the message that was sent.
channels = channelEditText.getText().toString();
message = messageEditText.getText().toString();
ParsePush push = new ParsePush();
push.setChannel(channels);
push.setMessage(message);
push.sendInBackground();
channelEditText.setText("");
messageEditText.setText("");
ParseObject notifications = new ParseObject("Notifications");
notifications.add("channels", channels);
notifications.put("msg", message);
notifications.saveInBackground();
My Android app's "Notification History" fragment then performs
ParseQueryAdapter<ParseObject> notificationAdapter =
new ParseQueryAdapter<ParseObject>(getActivity(), new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery<ParseObject> create() {
ParseQuery query = new ParseQuery("Notifications");
query.whereContainedIn("channels", ParseInstallation.getCurrentInstallation().getList("channels"));
query.orderByDescending("createdAt");
return query;
}
});
notificationAdapter.setTextKey("msg");
ListView notificationListView = (ListView) rootView.findViewById(R.id.notificationListView);
notificationListView.setAdapter(notificationAdapter);
My ParseApplication.java subscribes a user to channel: "Welcome" on installation so I don't receive a null pointer. The Notifications Table entry with channel "Welcome" populates the listview.
I have two ways to subscribe to a channel. One way is on the device itself like this
final EditText syncInput = (EditText) rootView.findViewById(R.id.syncInput);
Button syncButton = (Button) rootView.findViewById(R.id.syncButton);
syncButton.setOnClickListener(new OnClickListener() {
public void onClick(View v){
String sync = null;
sync = syncInput.getText().toString();
PushService.subscribe(getActivity(), sync, DashboardActivity.class);
syncInput.setText("");
}
});
The other way is through CloudCode
Parse.Cloud.define("subscribeToChannel", function(request, response){
var channelName = request.params.channel;
var userId = request.params.userId;
if(!channelName) {
response.error("Missing parameter: channel");
return;
}
if (!userId) {
response.error("Missing paremeter: userId");
return;
}
//Create a Pointer to the user based on their object id
var user = new Parse.User();
user.id = userId;
Parse.Cloud.useMasterKey();
// A user might have more than one installation
var query = new Parse.Query(Parse.Installation);
query.equalTo("user", user); //Match Installations with a pointer to this User
query.find({
success: function(installations) {
for (var i = 0; i < installations.length; i++) {
//Add the channel to al the installations for this user
installations[i].addUnique("channels", channelName);
}
//Save all the installations
Parse.Object.saveAll(installations, {
success: function(installations) {
//All the installations where saved.
response.success("All the installations were updated with this channel.");
},
error: function(error) {
//An error occured while saving one of the objects.
console.error(error);
response.error("An error occured while updating this user's installations.");
}
});
},
error: function(error) {
console.error(error);
response.error("An error occurred while looking up this user's installations");
}
});
});
Both ways of subscribing are successful in that a Push notification sent to the target channel reaches the device. Here is the issue... If I use the device to subscribe my query will show the messages sent to that channel that is saved in the Notifications table. If I use the CloudCode my query does NOT show the message sent to the channel that is saved in the Notification table.
I'm stumped. Any help is deeply appreciated.
--------------------------------SOLUTION-------------------------------------------------
protected void onResume() {
super.onResume();
ParseInstallation.getCurrentInstallation().refreshInBackground(new RefreshCallback(){
#Override
public void done(ParseObject parseObject, ParseException e) {
List<String> channels = ParseInstallation.getCurrentInstallation().getList("channels");
for (int i = 0; i < channels.size(); i++) {
Log.w("TEST", channels.get(i));
}
}
});
}
You're editing the Installation record on the server-side in Cloud Code, but the device isn't getting the updated data. If this is a common behavior in your app, refresh the installation object when you load the app:
ParseInstallation.getCurrentInstallation().refreshInBackground();
or fetchInBackground, as shown here: https://parse.com/docs/android_guide#objects-retrieving
This could also be solved by, instead of querying from the device, calling a cloud function which does the query (with the updated channels list already on the server-side.)

Categories

Resources