B4J Question Help with Parse

derez

Expert
Licensed User
Longtime User
I made a Family Tree app which updates the DB at several users using PARSE.
It works nice and I made an equivalent app with B4j but the PARSE lib is not compatible.
Agraham showed me their REST API https://parse.com/docs/rest#users-login
It looks like something that can be done using HTTP and HTTPUTILS but I have no experience. The examples are in PYTHON or CURL.
For example : login process
B4X:
import json,httplib,urllib
connection = httplib.HTTPSConnection('api.parse.com', 443)
params = urllib.urlencode({"username":"cooldude6","password":"p_n7!-e8"})
connection.connect()
connection.request('GET', '/1/login?%s' % params, '', {
"X-Parse-Application-Id": "${APPLICATION_ID}",
"X-Parse-REST-API-Key": "${REST_API_KEY}"
})
result = json.loads(connection.getresponse().read())
print result

I made a successful connection :
B4X:
skt.Initialize("skt")
skt.Connect("api.parse.com", 443,0)

But got lost afterwards. I guess it should be job1.download2() with the username & password (which I have).
After login I need to get objects and send objects.
If someone could help – I’ll appreciate.
 

derez

Expert
Licensed User
Longtime User
Now for the objects. Retrieving an object goes by the api like:
B4X:
connection.request('GET', '/1/classes/Family/QrJi9bK6ih', '', {
      "X-Parse-Application-Id": "vWcbP5PvajXyGcF123E0Z9F4tSCIwvS9AtIZmwCz",
      "X-Parse-REST-API-Key": "opBMoH2Qqguvx3eDhcwEAZ0Jdl4nuLUP5BgRZWZb"
    })
result = json.loads(connection.getresponse().read())

I tried this:
B4X:
 Dim j As HttpJob
j.Initialize("get_object", Me)
j.Download("https://api.parse.com/1/Classes/Family/QrJi9bK6ih")
j.GetRequest.SetHeader("X-Parse-REST-API-Key", "opBMoH2Qqguvx3eDhcwEAZ0Jdl4nuLUP5BgRZWZb")
j.GetRequest.SetHeader("X-Parse-Application-Id", "vWcbP5PvajXyGcF123E0Z9F4tSCIwvS9AtIZmwCz")

but get a false response, saying the page does not exist.
 
Upvote 0

derez

Expert
Licensed User
Longtime User
classes should be with c, not C, then I get the object :):D:
Program started.
[jobname=log-in, success=true, username=
, password=, errormessage=, target=class b4j.example.main
, taskid=1, req=anywheresoftware.b4a.http.HttpClientWrapper$HttpUriRequestWrapper@22c2, tag=java.lang.Object@ea2a0d
, fx=anywheresoftware.b4j.objects.JFX@16ed69e, httputils2service=null]
{"results":[{"username":"[email protected]","createdAt":"2013-12-06T10:17:22.432Z","updatedAt":"2013-12-06T10:17:22.432Z","objectId":"6M9j4kFywq"}]}
[jobname=get_object, success=true, username=
, password=, errormessage=, target=class b4j.example.main
, taskid=2, req=anywheresoftware.b4a.http.HttpClientWrapper$HttpUriRequestWrapper@13271bd, tag=java.lang.Object@c93402
, fx=anywheresoftware.b4j.objects.JFX@17597b6, httputils2service=null]
{"Birth":"6.3.1948","Country":"ישראל","Death":"","Fcod":143,"Gen":32,"Infobit":"0","Marriage":"12.8.1970","Mcod":144,"Misc":"","Nick":"מנחם","No":151,"Pic":1,"Prev_N":"רייס","Scod":152,"Sex":1,"Surname":"ארז","Time":1373827293060,"Town":"רמת השרון","jpg":{"__type":"File","name":"6622ab7c-1421-401d-9013-2e84a27e9fa9-151.jpg","url":"http://files.parse.com/368a804a-639.../6622ab7c-1421-401d-9013-2e84a27e9fa9-151.jpg"},"createdAt":"2013-07-14T13:43:13.844Z","updatedAt":"2013-12-08T12:02:26.468Z","objectId":"QrJi9bK6ih"}
now how do I retrieve an object by its fields, not by objectID ?
Should be a translation of this:
params = urllib.urlencode({"where":json.dumps({
"playerName": "Sean Plott",
"cheatMode": False
})})

And after that the download request without the objectid.
 
Last edited:
Upvote 0

derez

Expert
Licensed User
Longtime User
With this code I got all the records instead of one. How do I put the constraint "No" = 151 ?
or "updatedAt' (in ticks) > x
B4X:
  j.Download2("https://api.parse.com/1/classes/Family",Array As String("No","151"))
j.GetRequest.SetHeader("X-Parse-REST-API-Key", "opBMoH2Qqguvx3eDhcwEAZ0Jdl4nuLUP5BgRZWZb")
j.GetRequest.SetHeader("X-Parse-Application-Id", "vWcbP5PvajXyGcF123E0Z9F4tSCIwvS9AtIZmwCz")
 
Last edited:
Upvote 0

derez

Expert
Licensed User
Longtime User
Ok, with slight change since "No" is defined as number, not string:
B4X:
Array As String("where", "{""No"":151}"))

how do I get the response as a map or similar kind of object so I can get each field separately ? currently it is one long string:
[jobname=get_object, success=true, username=
, password=, errormessage=, target=class b4j.example.main
, taskid=2, req=anywheresoftware.b4a.http.HttpClientWrapper$HttpUriRequestWrapper@14be60b, tag=java.lang.Object@1ebdcd7
, fx=anywheresoftware.b4j.objects.JFX@1efb699, httputils2service=null]
{"results":[{"Birth":"6.3.1948","Country":"ישראל","Death":"","Fcod":143,"Gen":32,"Infobit":"0","Marriage":"12.8.1970","Mcod":144,"Misc":"","Nick":"מנחם","No":151,"Pic":1,"Prev_N":"רייס","Scod":152,"Sex":1,"Surname":"ארז","Time":1373827293060,"Town":"רמת השרון","jpg":{"__type":"File","name":"6622ab7c-1421-401d-9013-2e84a27e9fa9-151.jpg","url":"http://files.parse.com/368a804a-639.../6622ab7c-1421-401d-9013-2e84a27e9fa9-151.jpg"},"createdAt":"2013-07-14T13:43:13.844Z","updatedAt":"2013-12-08T12:02:26.468Z","objectId":"QrJi9bK6ih"}]}

I can play with regex but may be there is a shorter way.
 
Upvote 0

derez

Expert
Licensed User
Longtime User
Ok, never used it but I read it and it is simple. To update an object I shall use post with the same type of jason string.
Can you help also with "push notification" ?
 
Upvote 0

derez

Expert
Licensed User
Longtime User
I can't get the jason way of writing like Array As String("where", "{""No"":110}"))
but No < 110 , or No < variable_name.
I need to screen the results by udpate time greater than what is kept in the memory.

In b4a it is:
B4X:
Dim LoadQ As ParseQuery
LoadQ.Initialize("Family")
LoadQ.WhereGreaterThan("Time",last_update)

If I use in download2 the term "where$lt" and then "{""No"":110}" I get all numbers from 99 to 199. ??????:mad: Got it, it limits the number of results, not a filter :(
 
Last edited:
Upvote 0

derez

Expert
Licensed User
Longtime User
Thank you, I got this working:
B4X:
 Dim t As Long = 1386521952680
 j.Download2("https://api.parse.com/1/classes/Family", Array As String("where", "{""Time"":"&t&"}"))
I still don't know how to use query constraints like "less then"
 
Upvote 0

derez

Expert
Licensed User
Longtime User
Now for the files. I have a field named "jpg" and it contains a picture. When I get it from parse I get
this data about it:
{__type=File, name=cb522558-bc52-49b1-b38c-2bb88ff2dba6-151.jpg, url=http://files.parse.com/368a804a-639...cb522558-bc52-49b1-b38c-2bb88ff2dba6-151.jpg}
How can I get the file buffer ? (then I'll save it in the right place as a picture).
As I understand, the data in jpg is a pointer to the actual file which is stored elsewhere.

Similar question is about html files.

In b4a it worked like this: you get the data from jpg field
B4X:
Dim pf As ParseFile
pf = po.GetObject("jpg")
pf.Get("jpg",TaskId)
Then you get the file:
B4X:
Sub jpg_DoneGet (Success As Boolean, Data() As Byte, TaskID As Int)
Dim out As OutputStream
out = File.OpenOutput(File.DirRootExternal & "/Family/jpg", TaskID & ".jpg", False)
out.WriteBytes(Data,0,Data.Length)
out.Close
 
Last edited:
Upvote 0

derez

Expert
Licensed User
Longtime User
I have succeded in creating a new object line in parse db, using the following :
B4X:
Dim j As HttpJob
j.Initialize("new", Me)
Dim data As Map
data.Initialize
data.Put("No", 3000)
data.Put("Name", "דודו")
data.Put("Nick", "מנדל")
Dim gen As JSONGenerator
gen.Initialize(data)
'151  דוד  ארז  QrJi9bK6ih ' the last prarameter is the objectId

j.PostString("https://api.parse.com/1/classes/Family", gen.ToString)

j.GetRequest.SetHeader("X-Parse-REST-API-Key", "opBMoH2Qqguvx3eDhcwEAZ0Jdl4nuLUP5BgRZWZb")
j.GetRequest.SetHeader("X-Parse-Application-Id", "vWcbP5PvajXyGcF123E0Z9F4tSCIwvS9AtIZmwCz")
j.GetRequest.SetContentType("application/json")
I don't know how to update an existing line. According to the api I should use "Put" instead of "Post", and the objectId after the ".../Family/" in the url : "https://api.parse.com/1/classes/Family/QrJi9bK6ih" . I have the id and tried it with post but get error "the page not found". Anyway I would prefer to use phrase like "where", "{""No"":151}" to get the line to update, it can probably be done with the jason string.
Any suggestions please ?
 
Upvote 0

derez

Expert
Licensed User
Longtime User
I made it with downloading files :)
As I have shown in 35 above, the file is kept in a special url stored in a map in the result.
I used the following sub to get down to the result details, after the job is done using
B4X:
If job.jobname = "get_object" Then  show_line(job.getstring)
:
B4X:
Sub show_line(st As String)
Dim jp As JSONParser
jp.Initialize(st)
Dim map1 As Map
map1 = jp.NextObject
Dim result As List
result = map1.GetValueAt(0)
Log("size= " & result.size)
For i = 0 To result.Size - 1
    Dim m As Map = result.Get(i)
    Log(m.Get("No") & "  " & m.Get("Name") & "  " & m.Get("Surname")  & "  " & m.Get("objectId"))
    Dim m2 As Map
    m2 = m.Get("jpg")
    If m2.IsInitialized Then
        Dim j As HttpJob
        j.Initialize("pic",Me)
        j.Download(m2.Get("url"))
    end if
Next
End Sub
And in the job response I save the file:
B4X:
If job.jobname = "pic" Then
        Dim out As OutputStream
        out = File.OpenOutput("D:","151.jpg", False)
        job.GetBitmap.WriteToStream(out)
        out.Close
    End If

It is possible to get the file name also by m2.Get("name")
 
Last edited:
Upvote 0
Top