During my summer internship I worked on DreamFactory’s mobile SDKs. One cool thing (of many) about DreamFactory is they provide a range of client SDKs complete with great documentation and samples. My last blog post was about the work I’ve done with the DreamFactory iOS SDK. I also worked on improving the Android SDK, building a sample app, and enhancing the documentation. You can now find the the new and improved SDK on GitHub. Here are some important things to know when getting started with the Android SDK.
Android SDK 101
The DreamFactory Android SDK provides user-friendly access to both native and remote REST services that you make available through DreamFactory. Wrappers make API calls clean. Designed to be compatible with Android API 15+, the API uses the Apache HttpClient to send REST requests. If the Apache HttpClient doesn’t meet your needs, changing the library used by the DreamFactory Android SDK to something like volley or retrofit is straightforward.
Here are some examples of authentication and database CRUD using the Android SDK.
Login
The SDK provides the BaseAsycRequest class to help build and manage the request. Extend it and override its functions in this request.
public class UserLoginTask extends BaseAsyncRequest {<br> private final String mEmail;<br> private final String mPassword;<br> UserLoginTask(String email, String password) {<br> mEmail = email;<br> mPassword = password;<br> }
Override the setup method, which is called before the request is built. The general form of the URL is /rest/service/endpoint. Logging in uses the user service and the session endpoint.
<span> @Override</span><span><br class="kix-line-break"></span><span> protected void doSetup() throws ApiException, JSONException {</span><span><br class="kix-line-break"></span><span> callerName = "loginActivity"; // used as a tag in error messages</span><span><br class="kix-line-break"></span><span> serviceName = "user";</span><span><br class="kix-line-break"></span><span> endPoint = "session";</span>
<span> // include application name</span><span><br class="kix-line-break"></span><span> applicationName = AppConstants.APP_NAME;</span>
Send the login credentials to DreamFactory in the request body. Use an email and password pair to authenticate with DreamFactory.
<span> // post email and password to get back session id</span><span><br class="kix-line-break"></span><span> // need session id to make every call other than login and challenge</span>
<span> verb = "POST";</span><span><br class="kix-line-break"></span><span> requestBody = new JSONObject();</span><span><br class="kix-line-break"></span><span> requestBody.put("email", mEmail);</span><span><br class="kix-line-break"></span><span> requestBody.put("password", mPassword);</span><span><br class="kix-line-break"></span><span> } // end setup</span><span><br class="kix-line-break"></span>
Process the response from the server if we did not get an error. Check that we got a session_id back and store it for later.
<span> @Override</span><span><br class="kix-line-break"></span><span> protected void process_response(String response) throws ApiException, JSONException {</span><span><br class="kix-line-break"></span><span> // store the session_id to be used later on</span><span><br class="kix-line-break"></span><span> JSONObject jsonObject = new JSONObject(response);</span><span><br class="kix-line-break"></span><span> String session_id = jsonObject.getString("session_id");</span><span><br class="kix-line-break"></span><span> if(session_id.length() == 0){</span><span><br class="kix-line-break"></span><span> throw new ApiException(0, "did not get a valid session id in the response");</span><span><br class="kix-line-break"></span><span> }</span><span><br class="kix-line-break"></span><span> PrefUtil.putString(getApplicationContext(), AppConstants.SESSION_ID, session_id);</span><span><br class="kix-line-break"></span><span> }</span><span><br class="kix-line-break"></span><span id="docs-internal-guid-9f06c367-0993-7075-7211-b6e5c953c7c2"></span>
If the request completed successfully, move on to the next view. Otherwise, indicate that login failed on the UI.
<span><span id="docs-internal-guid-9f06c367-0993-7075-7211-b6e5c953c7c2"><span> @Override</span><span><br class="kix-line-break"></span><span> protected void onCompletion(boolean success) {</span><span><br class="kix-line-break"></span><span> mAuthTask = null;</span><span><br class="kix-line-break"></span><span> showProgress(false);</span><span><br class="kix-line-break"></span><span> if(success){</span><span><br class="kix-line-break"></span><span> showGroupListActivity();</span><span><br class="kix-line-break"></span><span> }</span><span><br class="kix-line-break"></span><span> else {</span><span><br class="kix-line-break"></span><span> mPasswordView.setError(getString(R.string.error_incorrect_password));</span><span><br class="kix-line-break"></span><span> mPasswordView.requestFocus();</span><span><br class="kix-line-break"></span><span> }</span><span><br class="kix-line-break"></span><span> }</span></span></span>
Getting relational records
In this example we are getting records from a MySQL database for a view that displays the contacts in a certain group. We are using the database service to access relational records from the contact_relationship table.
serviceName = "db";<br> endPoint = "contact_relationships";<br> verb = "GET";
We want to end up with contact records using a groupId. The form of contact_relationship records is {groupId, contactId}. We use a filter to select only contact_relationship records for the group we are displaying. A related param gets the contacts referenced by each relational record.
<span> queryParams = new HashMap<>();</span><span><br class="kix-line-break"></span><span> queryParams.put("filter", "contactGroupId=" + groupId);</span><span><br class="kix-line-break"></span><span> queryParams.put("related", "contacts_by_contactId");</span>
The header params provide the application name and a valid session token to authenticate access.
applicationName = AppConstants.APP_NAME;<br> sessionId = PrefUtil.getString(getApplicationContext(), AppConstants.SESSION_ID);
Deserialize the response from a JSON string to POJOs using jackson’s mapper. The response is an array of contact_relation records, each with a field containing a contact record. The onCompletion method was excluded for brevity. If the call is successful the onCompletion method displays the list of contacts.
ContactsRelationalRecords relationalRecords =<br> (ContactsRelationalRecords) ApiInvoker.deserialize(response, <br> "", <br> ContactsRelationalRecords.class); <br> contactRecords = new ArrayList<>();<br> for(ContactsRelationalRecord record : relationalRecords.record){<br> contactRecords.add(record.contacts_by_contact_id);<br> }
Android SDK sample app
Sample code is available on GitHub showing more database CRUD operations as well as file CRUD operations. The SDK also supports operations on other resources available through DreamFactory, such as user or system objects.
To get started with the sample app, set up DreamFactory using one of the methods listed on the wiki. Import the application:
Configure CORS:
Point the sample app at your DreamFactory URL and you’re ready to go.
More detailed setup instructions are available in the README.
I hope you find the Android SDK, documentation and sample app helpful. If you have any questions or feedback, feel free to let me know by posting to this forum thread.