B4A Library Parse Library – Push Notifications and Cloud Storage

Parse service is shutting down: http://blog.parse.com/announcements/moving-on/

Overview


This library is a rather extensive overhaul of and update to Erels’ original Parse library.

Parse is a company that provides several services for mobile applications and has just been purchased by Facebook so it looks like it should continue to be a stable and reliable service.

You create an account on Parse.com and then create what they call “Applications” which would usually correspond with individual Android applications but don’t have to, so several different Android applications could access a common body of data in a single Parse application. Within Parse applications there are “Classes” of data which look much like a database table and contain ParseObjects which look like an individual row of data in a table.

Capabilities

The two major uses for this library are as follows

1) Providing cloud based data storage and retrieval for data held in the individual Parse Applications in a simple way including querying the stored data. No need to mess with HTTP and networking, it is all done for you in an object oriented fashion.

2) Supporting Push Notifications which can be instigated both from the Parse Web Dashboard of your Parse account and, if you have enabled it in the Dashboard for that Parse application, also from devices running the corresponding Android application. Push Notifications are sent in the context of the individual Parse Applications whose Android applications have registered to receive them but individual devices, or groups of devices, may be selectively targeted by using “Channels”.

Parse offer three levels of service, the first being free as long as you keep within their limits which are one million API Requests per month, one million Push Notifications per month and one Gigabyte of storage use. You can exceed these limits without upgrading to the next paid plan, which is presently 199 US dollars per month if you register a credit card. You can exceed these limits and be charged 7 US cents per one thousand excess API Requests, 20 UC cents per one thousand Pushes and 20 US cents per one Gigabyte of excess storage. There is information on your usage of all three available in your Parse Dashboard.

An API Request is a single network operation which are the ones that raise Basic4android events from the library.

The definition of the number of Pushes is “The total number of push notifications queued for delivery to a client device”. I may be being stupid but that seems ambiguous to me and I don’t understand whether that means that the total number of Push Notifications counts as each single message sent to lots of devices or as the total number of devices to which a single message is sent. I suspect the latter. If anyone knows definitively than please post and I will amend this paragraph.

The amount of storage used is obvious and needs no explanation.

Please read the Parse Android Guide, in the Parse.com Documentation section of their web site, for more information about how to use this library. The Parse Android API document might also be useful occasionally. The mapping of this library objects methods to those of the Java API are usually obvious.

All the operations which need to access the Parse online service are done asynchronously and raise events when complete whose parameters include a Success indication. If an error occurs Success will be False and a ParseException with a message describing the error will be placed in LastException. If necessary this should be processed in the event code as there is a possibility that a further error could occur in another asynchronous call that would overwrite the existing LastException.

Note that these asynchronous operations do not necessarily complete in the order in which they are invoked. To deal with this possibility a TaskID parameter is provided in each call that can be used, if required, to identify which of several possible method calls has just completed.

Installation instructions

In order to use this library you should sign up to Parse.com, go to your Dashboard and create a new Parse application called whatever you feel like calling it. You will need two keys, Application Id and Client Key, which you will find under the Settings for your application. Both are required and need to be copied to the appropriate Process Global variables in the demo.

You also need to download the Parse Android SDK from the Downloads section of the Parse.com web site. Inside the zip file you will find a file named Parse-1.2.4.jar or similar. Copy this to your Additional Libraries folder and rename it ParseNative.jar. Also put Parse.jar and Parse.xml from the demo archive in your Additional Libraries folder.

As detailed in the help for Parse. EnableNotifications in order for your application to receive Push Notifications you need to add the following to the Manifest Editor in your project.
B4X:
SetApplicationAttribute(android:name,"anywheresoftware.b4a.objects.ParseObjectWrapper$ParseApplication")

AddApplicationText(<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParseBroadcastReceiver">
  <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
    <action android:name="android.intent.action.USER_PRESENT" />
  </intent-filter>
</receiver>)

Version 1.1 of this library specified the Parse keys in a Parse.Initialize method. This method no longer exists in version 1.2 and later. This is because it it was called from within an Activity, but if Android killed your process and then tried to restart the Parse Service this failed because the service started without the activity being created and so was not initialised correctly. Initialisation now occurs on Application creation and requires the library Application class name to be registered in the manifest and the Parse keys to be specified as an xml resource. When the application is loaded you will see the values in the xml file echoed to the filtered logs.

You also need to place a file called res.xml in your project Objects/res/xml folder and make it read-only. The xml folder does not exist in the project archive but will be created at your first compile. The contents of res.xml should specify your Parse keys as follows
B4X:
<!--?xml version="1.0" encoding="utf-8"?-->
<data>
   <data1 value="YourParseApplicationAppID" />
   <data2 value="YourParseApplicationClientKey" />
</data>

The demo project is already set up to receive push notifications. Try sending one from your Parse Application using the Parse Dashboard.

Run the demo and have a play.

Issues

I have found that using IE10 to send a Push from the Parse Dashboard usually causes the Push to be sent twice, you will see this in the Dashboard list of pushes sent and also at the device and of course they both count towards your free total. Chrome appears to work correctly and sends only one. The work-around is obvious.

The Parse library starts a service called PushService to receive the Pushes and which you can see in Settings -> Apps -> Running -> ParseDemo. Prior to Parse SDK 1.2.4 sometimes this service stopped receiving Pushes and the Process needed to be stopped using a Task Manager and restarted. Parse SDK 1.2.5 should have fixed this.

EDIT:- Version 1.2 now posted. See post #6 for details.

EDIT:- Version 1.3 now posted. See post #13 for details.

EDIT:- Version 1.4 now posted. See post #17 for details.
 

Attachments

  • Parse1.4.zip
    43.2 KB · Views: 1,217
Last edited by a moderator:

ArminKH

Well-Known Member
is there any way to remove Start At Boot permision from this library?
 

Marvinb

New Member
Licensed User
Longtime User
I am trying to run a ParseDemo but it shows an error while trying to connect with my phone through wifi. this is the error 'src\b4a\example\parse\main.java:355: error: package anywheresoftware.b4a.objects.ParseObjectWrapper does not exist
public static anywheresoftware.b4a.objects.ParseObjectWrapper.ParseWrapper _parse = null;' have anyone came across this?
 

jamesnz

Active Member
Licensed User
Longtime User
Parse can do some very clever user authentication through Facebook Google etc but we need the parse user functionality. If anyone is interested in adding this is be keen to help pay for the time. If so let me know and I'll post a job in the jobs section.
 

stu14t

Active Member
Licensed User
Longtime User
Parse can do some very clever user authentication through Facebook Google etc but we need the parse user functionality. If anyone is interested in adding this is be keen to help pay for the time. If so let me know and I'll post a job in the jobs section.

I've been messing about with inline Java code. Now the following allows you to login (if you already have a user created inside Parse) but I'm having issues with the callback from the login sub in the Parse Jar.

This code logs you in and if you have an account returns the objectID of that user account. You could use that to validate the login process by checking an ObjectID is returned but If someone could help with the callback this would not be needed.

My code is not elegant i'm afraid but it works. You will need to substitute your own Master / Application keys where you see XXXXXXXXX

B4X:
#AdditionalJar: ParseNative

#If JAVA
import com.parse.ParseUser;
public String getCurrentUserId() {

    String objectId = "";
 
    ParseUser user = ParseUser.getCurrentUser();
    if(user != null) {
        objectId = user.getObjectId();
        return objectId;
    } else {
        return "";
    }
 
}
#End If

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Dim Parseint As Parse
    Dim UserName As String
    Dim Password As String
    Dim Result As Object
 
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Private Login As Button
    Private TxtUsername As EditText
    Private TxtPassword As EditText
    Private NativeMe As JavaObject
    Private BtnLogout As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
 
 
    Parseint.Initialize("XXXXXXXXXXXXXXXXXXXXX","XXXXXXXXXXXXXXXXXXXXX")
 
    If FirstTime Then 
     NativeMe.InitializeContext
 
    End If
 
    Activity.LoadLayout("Main")
 
 

End Sub

Sub ParseLogin As JavaObject
    Dim PL As JavaObject
    Dim jo As JavaObject
  
    'Use the JavaObject to access the ParseUser & LoginCallback
    PL.InitializeStatic("com.parse.ParseUser")
    jo.InitializeStatic("com.parse.LoginCallBack")
 
    'Run the Login Static method
    Dim callback As Object = jo.CreateEventFromUI("LoginCallBack", "Callback",Null)
    Result = PL.RunMethod("logInInBackground" , Array As Object (UserName,Password,callback))
 
    'Run the Inline Java to get the ObjectId of the CurrentUser 
    Dim s As String = NativeMe.RunMethod("getCurrentUserId", Null) 
 
    Log(Result)
    Log(s)
 
 
End Sub
Sub Callback_Event (MethodName As String, Args() As Object) As Object
   Log(MethodName & "   "  & Args)
End Sub
Sub Activity_Resume
 

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub



Sub Login_Click

    UserName = TxtUsername.Text
    Password = TxtPassword.Text
 
    ParseLogin 
 
End Sub
Sub BtnLogout_Click

    Dim logout As JavaObject
 
    logout.InitializeStatic("com.parse.ParseUser")
 
    logout.RunMethod("logOut",Null)
 
    Dim s As String = NativeMe.RunMethod("getCurrentUserId", Null) 
 
    Log(s)
 
End Sub
 

Kwame Twum

Active Member
Licensed User
Longtime User
Hello everyone, I keep getting "Unfortunately, ParseDemo has stopped" as soon as the app starts.
Nothing gets printed to the logs... both filtered and unfiltered
What could be wrong please?
 

hookshy

Well-Known Member
Licensed User
Longtime User
Hello everyone, I keep getting "Unfortunately, ParseDemo has stopped" as soon as the app starts.
Nothing gets printed to the logs... both filtered and unfiltered
What could be wrong please?
You can post code to track your errors ... For example when you read a key that does not have correct formatting the app will crash without any explanations
 

Kwame Twum

Active Member
Licensed User
Longtime User
You can post code to track your errors
Thanks @hookshy
I downloaded the sample from here... created my res.xml file (as specified with my keys), made it readonly.... no need to modify manifest as it's already done in the sample. Then I run the app and got that message on the phone...
B4A version: 5.20
TargetSdkVersion: 21
 

hookshy

Well-Known Member
Licensed User
Longtime User
I wanted to find an answer but searching the parse forum i found out that query is done
for max 1000 items
but note that query.limit=-1 as documented in b4a library does not work and gets only 100 itmes
in advance you must set up query.limit=1000

B4X:
 Dim query As ParseQuery
  query.Initialize("feed")
  query.Limit=-1 ,'????? this condition retrieves only 100 elements
  query.Find("get_feed", 1)
 
Last edited:

Serdar K.

Member
Licensed User
Longtime User
If someone wants to use the latest version of the library (1.4), here are Parse.com ' s older SDK files.
https://github.com/yongjhih/parse-android-sdk

I tried and managed to make the demo code work with agraham's library (i only removed the notification and push part, but i don't think it will change the result.)
It's working very well with Parse-1.7.0.jar as ParseNative.jar

Thanks everyone contributing this platform beginning with Erel.
Also i would like to send my special thanks to agraham also.
 

hookshy

Well-Known Member
Licensed User
Longtime User
I have problems with queryby Id ... It works only on main activity
If I run the code with another activity I get this error Sub test_done_get signature does not mach expected signature

Any ideas what shall I change ?
Thank you

B4X:
Sub feed_click

Dim query As ParseQuery
query.Initialize("feed")
query.GetById("test",docid,2)
ToastMessageShow("get_feed",True)
End Sub

Sub test_DoneGet(Success As Boolean, PO As ParseObject, TaskId As Int)
' java.lang.Exception Sub test_done_get signature does not mach expected signature

end sub
 

Serdar K.

Member
Licensed User
Longtime User
I have problems with queryby Id ... It works only on main activity
If I run the code with another activity I get this error Sub test_done_get signature does not mach expected signature

Any ideas what shall I change ?
Thank you

B4X:
Sub feed_click

Dim query As ParseQuery
query.Initialize("feed")
query.GetById("test",docid,2)
ToastMessageShow("get_feed",True)
End Sub

Sub test_DoneGet(Success As Boolean, PO As ParseObject, TaskId As Int)
' java.lang.Exception Sub test_done_get signature does not mach expected signature

end sub

I could suggest you to delete application data and cache on the device, then uninstall the application from the device and reinstall the application. After trying many different libraries this helped me.
 

hookshy

Well-Known Member
Licensed User
Longtime User
I could suggest you to delete application data and cache on the device, then uninstall the application from the device and reinstall the application. After trying many different libraries this helped me.
I tried but it seems it might be something else going on .... problem is with the my activity but I did not found yet
 

pesquera

Active Member
Licensed User
Longtime User
Hi, I have an app using this library.. working wonderful! I should migrate it with time.. any advice or idea about replacing this service will be appreciated.. thanks!
 

Serdar K.

Member
Licensed User
Longtime User
One possible alternative is to get a VPS and use B4J to implement the back end.
Start with jRDC and the push server.

Prices for VPS can be as low as 10$ per month.

I just made it work and they shut it down. :)

Anyway, we have to find a solution.They announced a couple days ago their planned shutdown after 1 year. They suggest to migrate to other cloud services. I myself think of moving to Google Cloud SQL or VPS hosted MySQL as a long term solution.

Alternatively, they made "most of the" Parse server sources available open, but the matter was the service and cloud support.
One single server is not reliable as a cloud platform with several backup servers on a network. It costs money to have that servers on our own.

It's a shame that they choose to shut Parse down.
 
Last edited:

Gentry

Member
Licensed User
Longtime User
Any chance that the B4A Parse Library can be adjusted to support moving the URLS so folks can point their B4A apps toward a private migrated Parse environment? If not, any chance the B4A library source code can be released to allow us to make that modification?

Thanks
 

Gentry

Member
Licensed User
Longtime User
Erel, thank you. Looks like the change to the wrapper should be like this:

B4X:
    /**
     *Add to Manifest Editor
     *SetApplicationAttribute(android:name,"anywheresoftware.b4a.objects.ParseObjectWrapper$ParseApplication")
     *
     *Add to file res/xml/res.xml replacing with the ppropriate keys and make read-only
     *<!--?xml version="1.0" encoding="utf-8"?-->
     *<data>
     *    <data1 value="YourAppId" />
     *    <data2 value="YourClientKey" />
     *     <data3 value="ParseServerURL" />
     *</data>
     *
     */
    public static class ParseApplication extends Application
    {

        @Override
        public void onCreate()
        {
            String appID = "";
            String clientKey = "";
            String serverURI = "";
          
            super.onCreate();

            Resources res = this.getResources();
            int id = res.getIdentifier("res", "xml", this.getPackageName());
            Log.v("B4A","ParseApplication.onCreate xml Id = " + id);
            XmlResourceParser xml = res.getXml(id);
            int eventType;
            try
            {
                eventType = xml.getEventType();
                while (eventType != XmlPullParser.END_DOCUMENT)
                {
                    if (eventType == XmlPullParser.START_TAG)
                    {
                        Log.v("B4A",xml.getName() + " " + xml.getAttributeValue(null, "value"));
                        if (xml.getName().equals("data1"))
                            appID = xml.getAttributeValue(null, "value");
                        if (xml.getName().equals("data2"))
                            clientKey = xml.getAttributeValue(null, "value");
                        if (xml.getName().equals("data3"))
                            serverURI = xml.getAttributeValue(null, "value");
                    }
                    eventType = xml.next();
                }
            } catch (Exception e)
            {
                Log.v("B4A", "ParseApplication exception: " + e.getMessage());
            }
            xml.close();
            Parse.initialize(this, appID, clientKey, serverURI);
        }
    }
}

Now.... I'll figure out how to compile the modified library and test it out...
 
Top