Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Drupal, Android and iPhone


Published on

Talk given at Drupalcamp Bucharest 2011.

Published in: Technology
  • Be the first to comment

Drupal, Android and iPhone

  1. 1. DRUPAL, ANDROID AND IPHONE Badiu Alexandru Fratu Mihai Drupalcamp Bucharest 2011
  2. 2. ABOUT US• We work at Adulmec• We do fine products such as Dealfever, Urbo and Adulmec• We sometime build mobile apps• Ataxi, Urbo, games and soon the Adulmec app Drupalcamp Bucharest 2011
  3. 3. CONNECTI• You expose some functionality as REST or some sort of web service• Your mobile application makes HTTP calls• Authentication? Access control? Drupalcamp Bucharest 2011
  4. 4. CONNECTI• Two ways• Use the Services module• Use a custom solution• Depends on your requirements Drupalcamp Bucharest 2011
  5. 5. FOR• Adulmec Coupon Redeem - custom• Urbo - Services Drupalcamp Bucharest 2011
  6. 6. CUSTOM• Write php pages• Without Drupal• Lightweight Drupal• Full Drupal• Output XML or JSON• Make HTTP call and parse result Drupalcamp Bucharest 2011
  7. 7. CUSTOM• Latest news app• Shows a list of the latest posts on a site• Click on a post, go to the site Drupalcamp Bucharest 2011
  8. 8. <?php CUSTOMchdir(../);require_once ./includes/;drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);$response = array();$result = db_query_range(SELECT nid, title FROM {node} WHERE type="story" ORDERBY created DESC, 0, 10);while ($row = db_fetch_object($result)) { $response[] = array(title => $row->title, url => node/ . $row->nid);}drupal_json($response); Drupalcamp Bucharest 2011
  9. 9. CUSTOM[   {      "title":"Illum Verto Fere Esse Secundum Cui Zelus Luctus",      "url":"node/2"   },   {      "title":"Uxor Eu Camur Voco Refero Fere",      "url":"node/7"   },] Drupalcamp Bucharest 2011
  10. 10. CUSTOMURI uri = new URI("");HttpClient client = new DefaultHttpClient();HttpGet request = new HttpGet(uri);HttpResponse response = client.execute(request);InputStream is = response.getEntity().getContent();BufferedReader br = new BufferedReader(new InputStreamReader(is));String result = br.readLine();adapter.clear();JSONArray r = new JSONArray(result);for (int i = 0; i < r.length(); i++) { JSONObject jitem = r.getJSONObject(i); SubtitleItem item = new SubtitleItem(jitem.getString("title"),jitem.getString("url")); adapter.add(item);}adapter.notifyDataSetChanged(); Drupalcamp Bucharest 2011
  11. 11. SERVICES• Creates web services out of Drupal functions• Concepts: service and server• Autenthication plugins• Pluggable Drupalcamp Bucharest 2011
  12. 12. SERVICES• Out of the box: Comments, Files, Menu, Node, Search, System, Taxonomy, User, Views• XMLRPC Server• Key based authentication Drupalcamp Bucharest 2011
  13. 13. SERVICES• We use XMLRPC in iOS apps• We use JSON in Android apps• json_server• Demo with standard json parser• GSON and Jackson• Streaming and mapping Drupalcamp Bucharest 2011
  14. 14. SERVICES• Drupalcloud for Android• Custom code for iOS• drupal-ios-sdk Drupalcamp Bucharest 2011
  15. 15. SERVICES• Key auth allows you to grant access just to some specific apps• Fine-grained: user authentication• Session id is used in every call• system.connect Drupalcamp Bucharest 2011
  16. 16. SERVICES• hash - sha of domain, time and nonce• domain• timestamp• nonce• session Drupalcamp Bucharest 2011
  17. 17. SERVICES• call system.connect - get session• use session in every call• call user.login - get new session• use new session in every call• call user.logout• call system.connect - get session• repeat Drupalcamp Bucharest 2011
  18. 18. SERVICES• What about saving session across app launches?• Save session and timestamp to prefs after login or connect• At launch check that the saved session has not expired• If not, use that session• Otherwise system.connect Drupalcamp Bucharest 2011
  19. 19. WTFS• userLogin returns new session• no user uid• no way to set it in the client• we create our own• json_server does not work Drupalcamp Bucharest 2011
  20. 20. public void setSessionId(String sessionId) { SharedPreferences auth = mCtx.getSharedPreferences(mPREFS_AUTH, 0); SharedPreferences.Editor editor = auth.edit(); editor.putString("sessionid", sessionId); editor.putLong("sessionid_timestamp", new Date().getTime() / 100); editor.commit();} Drupalcamp Bucharest 2011
  21. 21. WTFS • Services is inconsistent or weird • You’re already logged in as... • Error is false or true? • Where’s the error?{ "#error": false, "#data": { "#error": true, "#message": "Wrongusername or password." } }{ "#error": false, "#data": { "sessid":"02fd1c8a9d37ed9709ba154320340e8a", "user": { "uid": "1", ... Drupalcamp Bucharest 2011
  22. 22. DRUPALCLclient = new JSONServerClient(this, getString(R.string.sharedpreferences_name), getString(R.string.SERVER), getString(R.string.API_KEY), getString(R.string.DOMAIN), getString(R.string.ALGORITHM), Long.parseLong(getString(R.string.SESSION_LIFETIME)));<string name="app_name">AndroidDemo</string><string name="sharedpreferences_name">AndroidDemoPrefs</string><string name="SERVER"></string><string name="API_KEY">85255b11393bc0ee19d29758a043a698</string><string name="DOMAIN"></string><string name="ALGORITHM">HmacSHA256</string><string name="SESSION.LIFETIME">1209600</string> Drupalcamp Bucharest 2011
  23. 23. DRUPALCL• Has some methods built in• Just parse the response• For other methods do Drupalcamp Bucharest 2011
  24. 24. DRUPALCLString result = client.userLogin(userText.getText().toString(),passText.getText().toString());JSONObject r = new JSONObject(result).getJSONObject("#data");boolean error;try { error = d.getBoolean("#error");}catch (Exception e) { error = false;}if (!error) { String session = d.getString("sessid"); client.setSessionId(session);}else { finish();} Drupalcamp Bucharest 2011
  25. 25. DRUPALCLtry { JSONObject node = new JSONObject(); node.put("type", "story"); node.put("title", title.getText().toString()); node.put("body", body.getText().toString()); BasicNameValuePair[] params = new BasicNameValuePair[1]; params[0] = new BasicNameValuePair("node", node.toString()); String result ="", params); } catch (Exception e) { Log.v("drupalapp", e.toString()); e.printStackTrace(); } Drupalcamp Bucharest 2011
  26. 26. RESOURCE• DrupalCloud• drupal-ios-sdk••• Drupalcamp Bucharest 2011
  27. 27. THANK http://ctrlz.roDrupalcamp Bucharest 2011